/**
 * Copyright (c) 2012-2016, www.tinygroup.org (luo_guo@icloud.com).
 * <p>
 * Licensed under the GPL, Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/gpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tinygroup.uienginestore.application;

import org.tinygroup.application.AbstractApplicationProcessor;
import org.tinygroup.commons.tools.StringUtil;
import org.tinygroup.config.util.ConfigurationUtil;
import org.tinygroup.logger.LogLevel;
import org.tinygroup.logger.Logger;
import org.tinygroup.logger.LoggerFactory;
import org.tinygroup.uienginestore.FileObjectStore;
import org.tinygroup.uienginestore.UIOperator;
import org.tinygroup.vfs.FileObject;
import org.tinygroup.vfs.VFS;
import org.tinygroup.weblayer.listener.ServletContextHolder;
import org.tinygroup.xmlparser.node.XmlNode;

import java.util.List;

/**
 * UIEngine应用处理器
 * @author yancheng11334
 *
 */
public class UIEngineStoreProcessor extends AbstractApplicationProcessor {

    protected static final Logger LOGGER = LoggerFactory
            .getLogger(UIEngineStoreProcessor.class);

    private XmlNode applicationConfig;
    private XmlNode componentConfig;

    private FileObjectStore fileObjectStore;

    private UIOperator uIOperator;

    public FileObjectStore getFileObjectStore() {
        return fileObjectStore;
    }

    public void setFileObjectStore(FileObjectStore fileObjectStore) {
        this.fileObjectStore = fileObjectStore;
    }

    public UIOperator getuIOperator() {
        return uIOperator;
    }

    public void setuIOperator(UIOperator uIOperator) {
        this.uIOperator = uIOperator;
    }

    public void start() {
        LOGGER.logMessage(LogLevel.INFO, "UIEngine应用处理器操作UI资源开始...");

        XmlNode totalConfig = ConfigurationUtil.combineXmlNode(applicationConfig, componentConfig);
        String storePath = totalConfig == null ? null : totalConfig.getAttribute("storePath");
        if (StringUtil.isEmpty(storePath)) {
            LOGGER.logMessage(LogLevel.WARN, "没有找到UI资源存储路径,请检查是否配置storePath存储路径");
        } else {
            boolean mergeTag = totalConfig == null ? true : Boolean.parseBoolean(totalConfig.getAttribute("mergeTag", "true"));
            processJs(storePath, mergeTag);
            processCss(storePath, mergeTag);
        }
        LOGGER.logMessage(LogLevel.INFO, "UIEngine应用处理器操作UI资源结束.");
    }

    public void stop() {

    }

    public String getApplicationNodePath() {
        return "/application/uiengine-store";
    }

    public String getComponentConfigPath() {
        return "/uienginestore.config.xml";
    }

    public void config(XmlNode applicationConfig, XmlNode componentConfig) {
        this.applicationConfig = applicationConfig;
        this.componentConfig = componentConfig;
    }

    public XmlNode getComponentConfig() {
        return componentConfig;
    }

    public XmlNode getApplicationConfig() {
        return applicationConfig;
    }

    public int getOrder() {
        return 0;
    }

    private void processJs(String storePath, boolean mergeTag) {
        LOGGER.logMessage(LogLevel.INFO, "UIEngine应用处理器操作JS开始...");

        try {
            List<FileObject> fileObjects = createJs(mergeTag);
            for (FileObject source : fileObjects) {
                storeResource(source, storePath);
            }
        } catch (Exception e) {
            LOGGER.errorMessage("UIEngine应用处理器操作JS发生异常,存储路径[{0}]", e, storePath);
        }

        LOGGER.logMessage(LogLevel.INFO, "UIEngine应用处理器操作JS结束.");
    }

    private List<FileObject> createJs(boolean mergeTag) throws Exception {
        return uIOperator.createJS(mergeTag);
    }

    private void storeResource(FileObject source, String storePath) throws Exception {
        String path = computeStorePath(source, storePath);
        FileObject target = null;
        try {
            target = VFS.resolveFile(path);
            fileObjectStore.store(source, target);
        } finally {
            if (source != null) {
                source.clean();
            }
            if (target != null) {
                target.clean();
            }
        }
    }

    private String computeStorePath(FileObject source, String storePath) {
        StringBuilder sb = new StringBuilder();
        sb.append(storePath); //添加存储前缀
        boolean endtag = storePath.endsWith("/");
        boolean starttag = source.getPath().startsWith("/");
        if (endtag) {
            if (starttag) {
                sb.append(source.getPath().substring(1));
            } else {
                sb.append(source.getPath());
            }
        } else {
            if (starttag) {
                sb.append(source.getPath());
            } else {
                sb.append("/").append(source.getPath());
            }
        }
        return sb.toString();
    }

    private void processCss(String storePath, boolean mergeTag) {
        LOGGER.logMessage(LogLevel.INFO, "UIEngine应用处理器操作CSS开始...");
        try {
            List<FileObject> fileObjects = createCss(mergeTag);
            for (FileObject source : fileObjects) {
                storeResource(source, storePath);
            }
        } catch (Exception e) {
            LOGGER.errorMessage("UIEngine应用处理器操作CSS发生异常,存储路径[{0}]", e, storePath);
        }
        LOGGER.logMessage(LogLevel.INFO, "UIEngine应用处理器操作CSS结束.");
    }

    private List<FileObject> createCss(boolean mergeTag) throws Exception {
        String contextPath = ServletContextHolder.getServletContext().getContextPath();
        return uIOperator.createCSS(contextPath, "/uiengine.uicss", mergeTag);
    }

}
